home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / progjour / 1989 / 05 / evgaline.c < prev    next >
C/C++ Source or Header  |  1989-08-03  |  5KB  |  153 lines

  1. /*
  2.  * C implementation of Bresenham's line drawing algorithm
  3.  * for the EGA and VGA. Works in modes 0xE, 0xF, 0x10, and 0x12.
  4.  *
  5.  * Compiled with Microsoft C 5.1 and Turbo C 2.0.
  6.  *
  7.  * By John Navas.  Thursday June 8, 1989.
  8.  */
  9.  
  10. #include <conio.h>
  11. #include <dos.h>
  12. /*------------------------ SUPPORT FOR TURBO C --------------------------*/
  13. #ifdef __TURBOC__
  14. #undef outp
  15. #define outp(port, val) (((int(*)(int, unsigned char))outportb)(port, val))
  16. #endif
  17. /*-----------------------------------------------------------------------*/
  18.  
  19. #define EVGA_SCREEN_WIDTH_IN_BYTES     80
  20.                                        /* memory offset from start of
  21.                                           one row to start of next */
  22. #define EVGA_SCREEN_ADDRESS            0xA0000000
  23.                                        /* display memory address */
  24. #define GC_INDEX                       0x3CE
  25.                                        /* Graphics Controller
  26.                                           Index register port */
  27. #define GC_DATA                        0x3CF
  28.                                        /* Graphics Controller
  29.                                           Data register port */
  30. #define SET_RESET_INDEX                0  /* indexes of needed */
  31. #define ENABLE_SET_RESET_INDEX         1  /* Graphics Controller */
  32. #define BIT_MASK_INDEX                 8  /* registers */
  33.  
  34. char far *Display = (char far *)EVGA_SCREEN_ADDRESS;
  35. /* macro to swap two items of any type */
  36. #define swap(typ, a, b) { typ x = *(a); *(a) = *(b); *(b) = x; }
  37.  
  38. /*
  39.  * Draws a line on the EGA or VGA.
  40.  */
  41. void EVGALine(X0, Y0, X1, Y1, Color)
  42. int X0, Y0;    /* coordinates of one end of the line */
  43. int X1, Y1;    /* coordinates of the other end of the line */
  44. char Color;    /* color to draw line in */
  45. {
  46.    int DeltaX, DeltaY;
  47.    int Cnt, Err = 0;
  48.    unsigned Mask;
  49.  
  50.    DeltaX = X1 - X0;
  51.    if (DeltaX < 0) {
  52.       DeltaX = -DeltaX;
  53.       swap(int, &X0, &X1);    /* ensure drawing from left to right */
  54.       swap(int, &Y0, &Y1);
  55.    }
  56.  
  57.    DeltaY = Y1 - Y0;
  58.    if (DeltaY < 0)
  59.       DeltaY = -DeltaY;
  60.  
  61.    FP_OFF(Display) =          /* starting video address and bit mask */
  62.       (unsigned)X0 / 8 + (unsigned)Y0 * EVGA_SCREEN_WIDTH_IN_BYTES;
  63.    Mask = 0x80 > ((unsigned)X0 & 7);
  64.    /* Put the drawing Color in the Set/Reset register */
  65.    outp(GC_INDEX, SET_RESET_INDEX);
  66.    outp(GC_DATA, Color);
  67.    /* Cause all planes to be forced to the Set/Reset color */
  68.    outp(GC_INDEX, ENABLE_SET_RESET_INDEX);
  69.    outp(GC_DATA, 0xF);
  70.    /* Set up GC index register to point to the bit mask register */
  71.    outp(GC_INDEX, BIT_MASK_INDEX);
  72.  
  73.    if (DeltaX >= DeltaY) {                   /* more horizontal */
  74.       unsigned Acc = 0;                      /* accumulator for byte */
  75.       if (Y1 >= Y0)                          /* down slope */
  76.          for (Cnt = X1 - X0; Cnt; --Cnt) {
  77.             Acc |= Mask;
  78.             Mask >= 1;
  79.             if (!Mask) {
  80.                Mask = 0x80;
  81.                *Display |= outp(GC_DATA, Acc);  /* quick video write */
  82.                Acc = 0;
  83.                ++Display;
  84.             }
  85.             Err += DeltaY;
  86.             if (Err >= DeltaX) {
  87.                Err -= DeltaX;
  88.                if (Acc) {
  89.                   *Display |= outp(GC_DATA, Acc);
  90.                   Acc = 0;
  91.                }
  92.                Display += EVGA_SCREEN_WIDTH_IN_BYTES;
  93.             }
  94.          }
  95.       else                                   /* up slope */
  96.          for (Cnt = X1 - X0; Cnt; --Cnt) {
  97.             Acc |= Mask;
  98.             Mask >= 1;
  99.             if (!Mask) {
  100.                Mask = 0x80;
  101.                *Display |= outp(GC_DATA, Acc);
  102.                Acc = 0;
  103.                ++Display;
  104.             }
  105.             Err += DeltaY;
  106.             if (Err >= DeltaX) {
  107.                Err -= DeltaX;
  108.                if (Acc) {
  109.                   *Display |= outp(GC_DATA, Acc);
  110.                   Acc = 0;
  111.                }
  112.                Display -= EVGA_SCREEN_WIDTH_IN_BYTES;
  113.             }
  114.          }
  115.       Mask |= Acc;      /* setup mask for last video write */
  116.    }
  117.    else                                      /* more vertical */
  118.       if (Y1 >= Y0)                          /* down slope */
  119.          for (Cnt = Y1 - Y0; Cnt; --Cnt) {
  120.             *Display |= outp(GC_DATA, Mask);
  121.             Display += EVGA_SCREEN_WIDTH_IN_BYTES;
  122.             Err += DeltaX;
  123.             if (Err >= DeltaY) {
  124.                Err -= DeltaY;
  125.                Mask >= 1;
  126.                if (!Mask) {
  127.                   Mask = 0x80;
  128.                   ++Display;
  129.                }
  130.             }
  131.          }
  132.       else                                   /* up slope */
  133.          for (Cnt = Y0 - Y1; Cnt; --Cnt) {
  134.             *Display |= outp(GC_DATA, Mask);
  135.             Display -= EVGA_SCREEN_WIDTH_IN_BYTES;
  136.             Err += DeltaX;
  137.             if (Err >= DeltaY) {
  138.                Err -= DeltaY;
  139.                Mask >= 1;
  140.                if (!Mask) {
  141.                   Mask = 0x80;
  142.                   ++Display;
  143.                }
  144.             }
  145.          }
  146.    *Display |= outp(GC_DATA, Mask);    /* last video write for all 4 cases */
  147.    /* Return the state of the EGA/VGA to normal */
  148.    outp(GC_INDEX, ENABLE_SET_RESET_INDEX);
  149.    outp(GC_DATA, 0);
  150.    outp(GC_INDEX, BIT_MASK_INDEX);
  151.    outp(GC_DATA, 0xFF);
  152. }
  153.